//#define DEBUG_E
#ifndef compile_time_expression_h_included
#define compile_time_expression_h_included

#include <cmath>
#include <typeinfo>
#include <iostream>
#include <boost/mpl/at.hpp>
#include <boost/mpl/void.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/has_key.hpp>
#include <type_traits> 

namespace std
{
template<unsigned int>
struct GET;

template<typename T>
struct self;

}
namespace foelsche
{
namespace cte
{
template<int B>
struct int_value;

typedef int_value<0> zero;
typedef int_value<1> one;

template<typename TA, typename TB>
struct addition;
template<typename TA, typename TB>
struct multiplication;
template<typename X, typename IX>
struct pow_;
template<typename TA, typename TB>
struct subtraction;
template<typename IX>
struct x;
template<typename IX>
struct sqrt_;
template<typename IX>
struct sin_;
template<typename IX>
struct cos_;
template<typename TA, typename TB>
struct divison;
template<typename TX>
struct exp_;
template<typename TX>
struct log_;


template<int B, int C=0>
struct real_value
{	typedef real_value type;
	template<typename DIX>
	struct derivative
	{	typedef zero type;
	};
	template<typename TUPLE>
        double operator()(const TUPLE &_rX) const
        {	return B*std::pow(10.0, C);
        }
	inline friend std::ostream &operator<<(std::ostream &_r, const real_value &)
	{	return _r << B*std::pow(10.0, C);
	}
	template<typename MAP>
	struct substitute
	{	typedef real_value type;
	};
};

template<int B>
struct int_value
{	typedef int_value type;
	template<typename DIX>
	struct derivative
	{	typedef zero type;
	};
	template<typename TUPLE>
        inline int operator()(const TUPLE &_rX) const
        {	return B;
        }
	inline friend std::ostream &operator<<(std::ostream &_r, const int_value &)
	{	return _r << B;
	}
	template<typename MAP>
	struct substitute
	{	typedef int_value type;
	};
};


template<const double *P>
struct double_value
{	template<typename DIX>
	struct derivative
	{	typedef zero type;
	};
	typedef double_value type;
	template<typename TUPLE>
	inline double operator()(const TUPLE &_rX) const
	{	return *P;
	}
	inline friend std::ostream &operator<<(std::ostream &_r, const double_value &)
	{	return _r << *P;
	}
	template<typename MAP>
	struct substitute
	{	typedef double_value type;
	};
};

template<double (*P)(void)>
struct double_value_f
{	template<typename DIX>
	struct derivative
	{	typedef zero type;
	};
	typedef double_value_f type;
	template<typename TUPLE>
	inline double operator()(const TUPLE &_rX) const
	{	return (*P)();
	}
	inline friend std::ostream &operator<<(std::ostream &_r, const double_value_f &)
	{	return _r << (*P)();
	}
	template<typename MAP>
	struct substitute
	{	typedef double_value_f type;
	};
};


template<typename IX>
struct x
{	template<typename DIX>
	struct derivative
	{	typedef typename boost::mpl::if_<
			typename boost::is_same<
				IX,
				DIX
			>::type,
			one,
			zero
		>::type type;
	};
	typedef x type;
	template<typename TUPLE>
        inline double operator()(const TUPLE &_rX) const
        {	return std::GET<IX::value>()(_rX);
        }
	inline friend std::ostream &operator<<(std::ostream &_r, const x &)
	{	return _r << "x[" << IX::value << "]";
	}
	template<typename MAP>
	struct substitute
	{	typedef x type;
	};
};

template<typename X>
struct minus
{	template<typename I>
	struct derivative
	{	typedef typename minus<
			typename X::template derivative<I>::type
		>::type type;
	};
	template<typename TUPLE>
        inline double operator()(const TUPLE &_r) const
	{	return -X()(_r);
        }
	typedef minus type;
	inline friend std::ostream &operator<<(std::ostream &_r, const minus &)
	{	return _r << "-(" << X() << ")";
	}
	template<typename MAP>
	struct substitute
	{	typedef typename boost::mpl::if_<
			typename boost::mpl::has_key<MAP, minus>::type,
			typename boost::mpl::at<
				MAP,
				minus
			>::type,
			typename minus<typename X::template substitute<MAP>::type>::type
		>::type type;
	};
};


template<typename TA, unsigned int I>
struct simplify
{	typedef TA type;
};


template<>
struct simplify<minus<zero>, 0>
{	typedef zero type;
};


template<typename TA, unsigned int I>
struct simplify<minus<minus<TA> >, I>
{	typedef typename simplify<TA, 0>::type type;
};
template<typename TA>
struct simplify<minus<TA>, 0>
{	typedef typename simplify<
		minus<
			typename simplify<TA, 0>::type 
		>,
		1
	>::type type;
};

template<typename X, typename Y>
struct pow_
{	template<typename DIX>
	struct derivative
	{	typedef multiplication<
			log_<X>,
			Y
		> MULT;
		typedef multiplication<
			pow_,
			typename MULT::template derivative<DIX>::type
		> type;
	};
	template<typename TUPLE>
        inline double operator()(const TUPLE &x) const
	{	const double y = Y()(x);
		if (y == 0.5)
			return std::sqrt(X()(x));
		else
		if (y == -0.5)
			return 1.0/std::sqrt(X()(x));
		else
		if (y == 1.0)
			return X()(x);
		else
			return std::pow(X()(x), y);
        }
	typedef pow_ type;
	inline friend std::ostream &operator<<(std::ostream &_r, const pow_ &)
	{	return _r << "pow(" << X() << ", " << Y() << ")";
	}
	template<typename MAP>
	struct substitute
	{	typedef typename boost::mpl::if_<
			typename boost::mpl::has_key<MAP, pow_>::type,
			typename boost::mpl::at<
				MAP,
				pow_
			>::type,
			typename pow_<
				typename X::template substitute<MAP>::type,
				typename Y::template substitute<MAP>::type>::type
		>::type type;
	};
};


template<typename X, int i, unsigned int I>
struct simplify<pow_<X, real_value<0, i> >, I>
{	typedef one type;
};


template<typename X, int B, int C>
struct pow_<X, real_value<B, C> >
{	template<typename IX>
	struct derivative
	{	typedef typename multiplication<
			real_value<B, C>,
			typename multiplication<
				typename X::template derivative<IX>::type,
				typename pow_<
					X,
					typename subtraction<
						real_value<B, C>,
						one
					>::type
				>::type
			>::type
		>::type type;
	};
	template<typename TUPLE>
        inline double operator()(const TUPLE &x) const
	{	return std::pow(X()(x), real_value<B, C>()(x));
        }
	typedef pow_ type;
	inline friend std::ostream &operator<<(std::ostream &_r, const pow_ &)
	{	return _r << "pow(" << X() << ", " << real_value<B, C>() << ")";
	}
	template<typename MAP>
	struct substitute
	{	typedef typename boost::mpl::if_<
			typename boost::mpl::has_key<MAP, pow_>::type,
			typename boost::mpl::at<
				MAP,
				pow_
			>::type,
			typename pow_<typename X::template substitute<MAP>::type, real_value<B, C> >::type
		>::type type;
	};
};

template<typename X, int B, int C>
struct pow_<X, minus<real_value<B, C> > >
{	template<typename IX>
	struct derivative
	{	typedef typename multiplication<
			minus<real_value<B, C> >,
			typename multiplication<
				typename X::template derivative<IX>::type,
				typename pow_<
					X,
					typename subtraction<
						minus<real_value<B, C> >,
						one
					>::type
				>::type
			>::type
		>::type type;
	};
	template<typename TUPLE>
        inline double operator()(const TUPLE &x) const
	{	return std::pow(X()(x), -real_value<B, C>()(x));
        }
	typedef pow_ type;
	inline friend std::ostream &operator<<(std::ostream &_r, const pow_ &)
	{	return _r << "pow(" << X() << ", " << -real_value<B, C>() << ")";
	}
	template<typename MAP>
	struct substitute
	{	typedef typename boost::mpl::if_<
			typename boost::mpl::has_key<MAP, pow_>::type,
			typename boost::mpl::at<
				MAP,
				pow_
			>::type,
			typename pow_<typename X::template substitute<MAP>::type, minus<real_value<B, C> > >::type
		>::type type;
	};
};

template<typename X, int B>
struct pow_p;
template<typename X, int B>
struct pow_n;
template<typename X, int B>
struct pow_<X, int_value<B> >
{	typedef typename boost::mpl::if_<
		boost::mpl::bool_<(B > 0)>,
		pow_p<X, B>,
		typename boost::mpl::if_<
			boost::mpl::bool_<(B == 0)>,
			one,
			pow_n<X, B>
		>::type
	>::type::type type;
};
template<typename X, int B>
struct pow_p
{	typedef boost::mpl::vector<X> children;
	template<typename IX>
	struct derivative
	{	typedef typename multiplication<
			real_value<B, 0>,
			typename multiplication<
				typename X::template derivative<IX>::type,
				typename pow_<
					X,
					int_value<B - 1>
				>::type
			>::type
		>::type type;
	};
	template<typename TUPLE>
        inline double operator()(const TUPLE &x) const
	{	return X()(x)*typename pow_<X, int_value<B - 1> >::type()(x);
        }
	typedef pow_p type;
	inline friend std::ostream &operator<<(std::ostream &_r, const pow_p &)
	{	return _r << "pow(" << X() << ", " << int_value<B>() << ")";
	}
	template<typename MAP>
	struct substitute
	{	typedef typename boost::mpl::if_<
			typename boost::mpl::has_key<MAP, pow_p>::type,
			typename boost::mpl::at<
				MAP,
				pow_p
			>::type,
			typename pow_p<typename X::template substitute<MAP>::type, B>::type
		>::type type;
	};
};
template<typename X, int B>
struct pow_n
{	template<typename IX>
	struct derivative
	{	typedef typename multiplication<
			real_value<B, 0>,
			typename multiplication<
				typename X::template derivative<IX>::type,
				typename pow_<
					X,
					int_value<B - 1>
				>::type
			>::type
		>::type type;
	};
	template<typename TUPLE>
        inline double operator()(const TUPLE &x) const
	{	return typename pow_<X, int_value<B + 1> >::type()(x)/X()(x);
        }
	typedef pow_n type;
	inline friend std::ostream &operator<<(std::ostream &_r, const pow_n &)
	{	return _r << "pow(" << X() << ", " << int_value<B>() << ")";
	}
	template<typename MAP>
	struct substitute
	{	typedef typename boost::mpl::if_<
			typename boost::mpl::has_key<MAP, pow_n>::type,
			typename boost::mpl::at<
				MAP,
				pow_n
			>::type,
			typename pow_n<typename X::template substitute<MAP>::type, B>::type
		>::type type;
	};
};


template<typename TX, unsigned int I>
struct simplify<pow_<TX, one>, I>
{	//typedef boost::mpl::vector<TX, one> children;
	typedef typename simplify<TX, 0>::type type;
};


template<typename TX, unsigned int I>
struct simplify<pow_<TX, zero>, I>
{	//typedef boost::mpl::vector<TX, zero> children;
	typedef one type;
};

/*struct zero
{	template<typename IX>
	struct derivative
	{	typedef zero type;
	};
	template<typename TUPLE>
        inline double operator()(const TUPLE &x) const
	{	return 0;
        }
	typedef zero type;
	inline friend std::ostream &operator<<(std::ostream &_r, const zero &)
	{	return _r << 0;
	}
	template<typename MAP>
	struct substitute
	{	typedef zero type;
	};
};
*/

/*struct one
{	template<typename IX>
	struct derivative
	{	typedef zero type;
	};
	template<typename TUPLE>
        inline double operator()(const TUPLE &x) const
	{	return 1;
        }
	typedef one type;
	inline friend std::ostream &operator<<(std::ostream &_r, const one &)
	{	return _r << 1;
	}
	template<typename MAP>
	struct substitute
	{	typedef one type;
	};
};
*/

template<typename TA, typename TB>
struct addition
{	template<typename IX>
	struct derivative
	{	typedef typename addition<
			typename TA::template derivative<IX>::type,
			typename TB::template derivative<IX>::type
		>::type type;
	};
	template<typename TUPLE>
        inline double operator()(const TUPLE &x) const
	{	return TA()(x)+TB()(x);
        }
	typedef addition type;
	inline friend std::ostream &operator<<(std::ostream &_r, const addition &)
	{	return _r << "(" << TA() << ") + (" << TB() << ")";
	}
	template<typename MAP>
	struct substitute
	{	typedef typename boost::mpl::if_<
			typename boost::mpl::has_key<MAP, addition>::type,
			typename boost::mpl::at<
				MAP,
				addition
			>::type,
			typename addition<typename TA::template substitute<MAP>::type, typename TB::template substitute<MAP>::type>::type
		>::type type;
	};
};

template<>
struct simplify<addition<zero, zero>, 0>
{	typedef zero type;
};
template<>
struct simplify<addition<zero, zero>, 1>
{	typedef zero type;
};

template<typename TA, unsigned int I>
struct simplify<addition<TA, zero>, I>
{	typedef typename simplify<TA, 0>::type type;
};

template<typename TA, unsigned int I>
struct simplify<addition<zero, TA>, I>
{	typedef typename simplify<TA, 0>::type type;
};

template<typename TA, unsigned int I>
struct simplify<addition<TA, minus<TA> >, I>
{	typedef zero type;
};

template<typename TA, unsigned int I>
struct simplify<addition<minus<TA>, TA>, I>
{	typedef zero type;
};

template<typename TA>
struct simplify<addition<TA, TA>, 0>
{	typedef typename simplify<
		multiplication<
			int_value<2>,
			typename simplify<TA, 0>::type
		>,
		1
	>::type type;
};


template<typename TA, typename TB, unsigned int I>
struct simplify<addition<TA, minus<TB> >, I>
{	typedef typename simplify<
		typename subtraction<
			typename simplify<TA, 0>::type, 
			typename simplify<TB, 0>::type
		>::type,
		I + 1
	>::type type;
};
template<typename TA, typename TB>
struct simplify<addition<TA, TB>, 0>
{	typedef typename simplify<
		addition<
			typename simplify<TA, 0>::type,
			typename simplify<TB, 0>::type
		>,
		1
	>::type type;
};


template<typename TA, typename TB>
struct simplify<addition<multiplication<TA, TB>, multiplication<TB, TA> >, 0>
{	typedef typename simplify<
		multiplication<
			multiplication<
				typename simplify<TB, 0>::type, 
				typename simplify<TA, 0>::type
			>,
			int_value<2>
		>,
		0
	>::type type;
};


template<typename TA, typename TB, unsigned int I>
struct simplify<subtraction<multiplication<TA, TB>, multiplication<TB, TA> >, I>
{	typedef zero type;
};

template<typename TA, typename TB>
struct subtraction
{	template<typename IX>
	struct derivative
	{	typedef typename subtraction<
			typename TA::template derivative<IX>::type,
			typename TB::template derivative<IX>::type
		>::type type;
	};
	template<typename TUPLE>
        inline double operator()(const TUPLE &x) const
	{	return TA()(x)-TB()(x);
        }
	typedef subtraction type;
	inline friend std::ostream &operator<<(std::ostream &_r, const subtraction &)
	{	return _r << "(" << TA() << ") - (" << TB() << ")";
	}
	template<typename MAP>
	struct substitute
	{	typedef typename boost::mpl::if_<
			typename boost::mpl::has_key<MAP, subtraction>::type,
			typename boost::mpl::at<
				MAP,
				subtraction
			>::type,
			typename subtraction<typename TA::template substitute<MAP>::type, typename TB::template substitute<MAP>::type>::type
		>::type type;
	};
};

template<unsigned int I>
struct simplify<subtraction<zero, zero>, I>
{	typedef zero type;
};

template<typename TA, unsigned int I>
struct simplify<subtraction<TA, zero>, I>
{	typedef typename simplify<TA, 0>::type type;
};

template<typename TA>
struct simplify<subtraction<zero, TA>, 0>
{	typedef typename simplify<
		minus<
			typename simplify<TA, 0>::type
		>,
		0
	>::type type;
};


template<typename TA, unsigned int I>
struct simplify<subtraction<TA, TA>, I>
{	typedef zero type;
};


template<typename TA, typename TB>
struct simplify<subtraction<TA, minus<TB> >, 0>
{	typedef typename simplify<
		addition<
			typename simplify<TA, 0>::type, 
			typename simplify<TB, 0>::type
		>,
		0
	>::type type;
};
template<typename TA, typename TB>
struct simplify<subtraction<TA, TB>, 0>
{	typedef typename simplify<
		subtraction<
			typename simplify<TA, 0>::type, 
			typename simplify<TB, 0>::type
		>,
		1
	>::type type;
};

template<typename TA, typename TB>
struct divison
{	template<typename IX>
	struct derivative
	{	typedef typename subtraction<
			typename divison<
				typename TA::template derivative<IX>::type,
				TB
			>::type,
			typename multiplication<
				typename divison<
					TA,
					typename multiplication<TB, TB>::type
				>::type,
				typename TB::template derivative<IX>::type
			>::type
		>::type type;
	};
	template<typename TUPLE>
        inline double operator()(const TUPLE &x) const
	{	return TA()(x)/TB()(x);
        }
	typedef divison type;
	inline friend std::ostream &operator<<(std::ostream &_r, const divison &)
	{	return _r << "(" << TA() << ") / (" << TB() << ")";
	}
	template<typename MAP>
	struct substitute
	{	typedef typename boost::mpl::if_<
			typename boost::mpl::has_key<MAP, divison>::type,
			typename boost::mpl::at<
				MAP,
				divison
			>::type,
			typename divison<typename TA::template substitute<MAP>::type, typename TB::template substitute<MAP>::type>::type
		>::type type;
	};
};

template<typename TB>
struct simplify<divison<zero, TB>, 0>
{	typedef zero type;
};
template<typename TB>
struct simplify<divison<zero, TB>, 1>
{	typedef zero type;
};
template<typename TB>
struct simplify<divison<TB, TB>, 0>
{	typedef one type;
};
template<typename TB>
struct simplify<divison<TB, TB>, 1>
{	typedef one type;
};
template<typename TA, typename TB>
struct simplify<divison<TA, TB>, 0>
{	typedef typename simplify<
		divison<
			typename simplify<TA, 0>::type,
			typename simplify<TB, 0>::type
		>,
		1
	>::type type;
};
template<typename TA>
struct simplify<divison<TA, one>, 0>
{	typedef typename simplify<TA, 0>::type type;
};
template<typename TA>
struct simplify<divison<TA, one>, 1>
{	typedef typename simplify<TA, 0>::type type;
};
template<typename TA, unsigned int I>
struct simplify<divison<TA, minus<TA> >, I>
{	typedef minus<one> type;
};
template<typename TA, unsigned int I>
struct simplify<divison<minus<TA>, TA>, I>
{	typedef minus<one> type;
};
template<typename TA, typename TB>
struct multiplication
{	template<typename IX>
	struct derivative
	{	typedef typename addition<
			typename multiplication<
				TA,
				typename TB::template derivative<IX>::type
			>::type,
			typename multiplication<
				typename TA::template derivative<IX>::type,
				TB
			>::type
		>::type type;
	};
	//d(a*b)/dx = dadx*b + a*dbdx
	//a*b = int(dadx*b + a*dbdx, dx)
	//a*b - int(a*dbdx, dx) = int(dadx*b, dx)
	//int(a, dx)*b - int(int(a, dx)*dbdx, dx) = int(a*b, dx)
	template<typename TUPLE>
        inline double operator()(const TUPLE &x) const
	{	return TA()(x)*TB()(x);
        }
	typedef multiplication type;
	inline friend std::ostream &operator<<(std::ostream &_r, const multiplication &)
	{	return _r << "(" << TA() << ") * (" << TB() << ")";
	}
	template<typename MAP>
	struct substitute
	{	typedef typename boost::mpl::if_<
			typename boost::mpl::has_key<MAP, multiplication>::type,
			typename boost::mpl::at<
				MAP,
				multiplication
			>::type,
			typename multiplication<typename TA::template substitute<MAP>::type, typename TB::template substitute<MAP>::type>::type
		>::type type;
	};
};


template<typename TA>
struct simplify<multiplication<TA, zero>, 0>
{	typedef zero type; 
};
template<typename TA>
struct simplify<multiplication<TA, zero>, 1>
{	typedef zero type; 
};
template<typename TA, unsigned int I>
struct simplify<multiplication<sqrt_<TA>, sqrt_<TA> >, I>
{	typedef typename simplify<TA, 0>::type type; 
};

template<typename TA>
struct simplify<multiplication<zero, TA>, 0>
{	typedef zero type; 
};
template<typename TA>
struct simplify<multiplication<zero, TA>, 1>
{	typedef zero type; 
};
template<typename TA>
struct simplify<multiplication<one, TA>, 0>
{	typedef typename simplify<TA, 0>::type type; 
};
template<typename TA>
struct simplify<multiplication<TA, one>, 0>
{	typedef typename simplify<TA, 0>::type type; 
};
template<unsigned int I>
struct simplify<multiplication<one, one>, I>
{	typedef one type; 
};

template<typename TA, typename TB>
struct simplify<multiplication<TA, TB>, 0>
{	typedef typename simplify<
		multiplication<
			typename simplify<TA, 0>::type,
			typename simplify<TB, 0>::type
		>,
		1
	>::type type;
};
template<typename TA, typename TB, typename TC, typename TD, unsigned int I>
struct simplify<multiplication<divison<TA, TB>, divison<TC, TD> >, I>
{	typedef typename simplify<
		divison<
			typename simplify<multiplication<TA, TC>, 0>::type,
			typename simplify<multiplication<TB, TD>, 0>::type
		>,
		0
	>::type type;
};

template<typename TA, unsigned int I>
struct simplify<divison<TA, sqrt_<TA> >, I>
{	typedef typename simplify<sqrt_<TA>, 0>::type type;
};
template<typename TA, unsigned int I>
struct simplify<divison<sqrt_<TA>, TA>, I>
{	typedef typename simplify<
		divison<one, sqrt_<TA> >,
		0
	>::type type;
};
template<typename TA, typename TB, unsigned int I>
struct simplify<
	divison<
		multiplication<TA, TB>,
		TA
	>,
	I
>
{	typedef typename simplify<TB, 0>::type type;
};
template<typename TA, typename TB, unsigned int I>
struct simplify<
	divison<
		multiplication<TB, TA>,
		TA
	>,
	I
>
{	typedef typename simplify<TB, 0>::type type;
};

template<typename TX>
struct exp_
{	template<typename IX>
	struct derivative
	{	typedef typename multiplication<
			typename exp_<TX>::type,
			typename TX::template derivative<IX>::type
		>::type type;
	};
	template<typename TUPLE>
	inline double operator()(const TUPLE &x) const
	{	return std::exp(TX()(x));
	}
	typedef exp_ type;
	inline friend std::ostream &operator<<(std::ostream &_r, const exp_ &)
	{	return _r << "exp(" << TX() << ")";
	}
	template<typename MAP>
	struct substitute
	{	typedef typename boost::mpl::if_<
			typename boost::mpl::has_key<MAP, exp_>::type,
			typename boost::mpl::at<
				MAP,
				exp_
			>::type,
			typename exp_<typename TX::template substitute<MAP>::type>::type
		>::type type;
	};
};


template<unsigned int I>
struct simplify<exp_<zero>, I>
{	typedef one type;
};


template<typename TX>
struct log_
{	template<typename IX>
	struct derivative
	{	typedef typename divison<
			typename TX::template derivative<IX>::type,
			TX
		>::type type;
	};
	template<typename TUPLE>
	inline double operator()(const TUPLE &x) const
	{	return std::log(TX()(x));
	}
	typedef log_ type;
	inline friend std::ostream &operator<<(std::ostream &_r, const log_ &)
	{	return _r << "log(" << TX() << ")";
	}
	template<typename MAP>
	struct substitute
	{	typedef typename boost::mpl::if_<
			typename boost::mpl::has_key<MAP, log_>::type,
			typename boost::mpl::at<
				MAP,
				log_
			>::type,
			typename log_<typename TX::template substitute<MAP>::type>::type
		>::type type;
	};
};


template<unsigned int I>
struct simplify<log_<one>, I>
{	typedef zero type;
};

template<typename TX>
struct sin_
{	template<typename IX>
	struct derivative
	{	typedef typename multiplication<
			typename TX::template derivative<IX>::type,
			typename cos_<TX>::type
		>::type type;
	};
	template<typename TUPLE>
	inline double operator()(const TUPLE &x) const
	{	return std::sin(TX()(x));
	}
	typedef sin_ type;
	inline friend std::ostream &operator<<(std::ostream &_r, const sin_ &)
	{	return _r << "sin(" << TX() << ")";
	}
	template<typename MAP>
	struct substitute
	{	typedef typename boost::mpl::if_<
			typename boost::mpl::has_key<MAP, sin_>::type,
			typename boost::mpl::at<
				MAP,
				sin_
			>::type,
			typename sin_<typename TX::template substitute<MAP>::type>::type
		>::type type;
	};
};

template<unsigned int I>
struct simplify<sin_<zero>, I>
{	typedef zero type;
};
template<typename TX>
struct cos_
{	template<typename IX>
	struct derivative
	{	typedef typename multiplication<
			typename TX::template derivative<IX>::type,
			typename minus<typename sin_<TX>::type>::type
		>::type type;
	};
	template<typename TUPLE>
	inline double operator()(const TUPLE &x) const
	{	return std::cos(TX()(x));
	}
	typedef cos_ type;
	inline friend std::ostream &operator<<(std::ostream &_r, const cos_ &)
	{	return _r << "cos(" << TX() << ")";
	}
	template<typename MAP>
	struct substitute
	{	typedef typename boost::mpl::if_<
			typename boost::mpl::has_key<MAP, cos_>::type,
			typename boost::mpl::at<
				MAP,
				cos_
			>::type,
			typename cos_<typename TX::template substitute<MAP>::type>::type
		>::type type;
	};
};
template<typename TX>
struct tan_
{	template<typename IX>
	struct derivative
	{	typedef typename addition<
			one,
			typename multiplication<tan_, tan_>::type
		>::type ADD;
		typedef typename multiplication<
			ADD,
			typename TX::template derivative<IX>::type
		>::type type;
	};
	template<typename TUPLE>
	inline double operator()(const TUPLE &x) const
	{	return std::tan(TX()(x));
	}
	typedef tan_ type;
	inline friend std::ostream &operator<<(std::ostream &_r, const tan_ &)
	{	return _r << "tan(" << TX() << ")";
	}
	template<typename MAP>
	struct substitute
	{	typedef typename boost::mpl::if_<
			typename boost::mpl::has_key<MAP, tan_>::type,
			typename boost::mpl::at<
				MAP,
				tan_
			>::type,
			typename tan_<typename TX::template substitute<MAP>::type>::type
		>::type type;
	};
};
template<typename TX>
struct tanh_
{	template<typename IX>
	struct derivative
	{	typedef typename subtraction<
			one,
			typename multiplication<tanh_, tanh_>::type
		>::type ADD;
		typedef typename multiplication<
			ADD,
			typename TX::template derivative<IX>::type
		>::type type;
	};
	template<typename TUPLE>
	inline double operator()(const TUPLE &x) const
	{	return std::tanh(TX()(x));
	}
	typedef tanh_ type;
	inline friend std::ostream &operator<<(std::ostream &_r, const tanh_ &)
	{	return _r << "tanh(" << TX() << ")";
	}
	template<typename MAP>
	struct substitute
	{	typedef typename boost::mpl::if_<
			typename boost::mpl::has_key<MAP, tanh_>::type,
			typename boost::mpl::at<
				MAP,
				tanh_
			>::type,
			typename tanh_<typename TX::template substitute<MAP>::type>::type
		>::type type;
	};
};

template<unsigned int I>
struct simplify<cos_<zero>, I>
{	typedef one type;
};

template<typename TX>
struct sqrt_
{	template<typename IX>
	struct derivative
	{	typedef typename divison<
			typename TX::template derivative<IX>::type,
			multiplication<
				int_value<2>, 
				sqrt_<TX>
			>
		>::type type;
	};
	template<typename TUPLE>
	inline double operator()(const TUPLE &x) const
	{	return std::sqrt(TX()(x));
	}
	typedef sqrt_ type;
	inline friend std::ostream &operator<<(std::ostream &_r, const sqrt_ &)
	{	return _r << "sqrt(" << TX() << ")";
	}
	template<typename MAP>
	struct substitute
	{	typedef typename boost::mpl::if_<
			typename boost::mpl::has_key<MAP, sqrt_>::type,
			typename boost::mpl::at<
				MAP,
				sqrt_
			>::type,
			typename sqrt_<typename TX::template substitute<MAP>::type>::type
		>::type type;
	};
};

template<unsigned int I>
struct simplify<sqrt_<zero>, I>
{	typedef zero type;
};
template<unsigned int I>
struct simplify<sqrt_<one>, I>
{	typedef one type;
};
template<typename T, unsigned int I>
struct simplify<sqrt_<multiplication<T, T> >, I>
{	typedef typename simplify<T, 0>::type type;
};

template<typename TX>
struct asin_
{	template<typename IX>
	struct derivative
	{	typedef typename pow_<
			typename subtraction<
				one,
				typename multiplication<TX, TX>::type
			>::type,
			minus<divison<one, addition<one, one> > >
		>::type type;
	};
	template<typename TUPLE>
	inline double operator()(const TUPLE &x) const
	{	return std::asin(TX()(x));
	}
	typedef asin_ type;
	inline friend std::ostream &operator<<(std::ostream &_r, const asin_ &)
	{	return _r << "asin(" << TX() << ")";
	}
	template<typename MAP>
	struct substitute
	{	typedef typename boost::mpl::if_<
			typename boost::mpl::has_key<MAP, asin_>::type,
			typename boost::mpl::at<
				MAP,
				asin_
			>::type,
			typename asin_<typename TX::template substitute<MAP>::type>::type
		>::type type;
	};
};
template<typename TX>
struct acos_
{	template<typename IX>
	struct derivative
	{	typedef typename minus<
			typename pow_<
				typename subtraction<
					one,
					typename multiplication<TX, TX>::type
				>::type,
				minus<divison<one, addition<one, one> > >
			>::type
		>::type type;
	};
	template<typename TUPLE>
	inline double operator()(const TUPLE &x) const
	{	return std::acos(TX()(x));
	}
	typedef acos_ type;
	inline friend std::ostream &operator<<(std::ostream &_r, const acos_ &)
	{	return _r << "acos(" << TX() << ")";
	}
	template<typename MAP>
	struct substitute
	{	typedef typename boost::mpl::if_<
			typename boost::mpl::has_key<MAP, acos_>::type,
			typename boost::mpl::at<
				MAP,
				acos_
			>::type,
			typename acos_<typename TX::template substitute<MAP>::type>::type
		>::type type;
	};
};

template<unsigned int I>
struct simplify<asin_<zero>, I>
{	typedef zero type;
};


template<typename TX>
cos_<TX> cos(TX)
{	return cos_<TX>();
}

template<typename TX>
tan_<TX> tan(TX)
{	return tan_<TX>();
}

template<typename TX>
sin_<TX> sin(TX)
{	return sin_<TX>();
}

template<typename TX>
exp_<TX> exp(TX)
{	return exp_<TX>();
}

template<typename TX>
log_<TX> log(TX)
{	return log_<TX>();
}

template<typename TA, typename TB>
typename multiplication<TA, TB>::type operator*(TA, TB)
{	return multiplication<TA, TB>::type();
}

template<typename TA, typename TB>
typename divison<TA, TB>::type operator/(TA, TB)
{	return divison<TA, TB>::type();
}
template<typename TA, typename TB>
typename addition<TA, TB>::type operator+(TA, TB)
{	return addition<TA, TB>::type();
}

template<typename TA, typename TB>
typename subtraction<TA, TB>::type operator-(TA, TB)
{	return subtraction<TA, TB>::type();
}

template<typename TA>
typename minus<TA>::type operator-(TA)
{	return minus<TA>::type();
}


template<typename O, typename S, typename R, unsigned int I>
struct substitute;

template<typename O, typename S, typename R>
struct substitute<O, S, R, 0>
{	typedef typename substitute<O, S, R, 1>::type type;
};

template<typename O, typename S, typename R>
struct substitute<O, S, R, 1>
{	typedef typename substitute<O, S, R, 2>::type type;
};
template<typename O, typename S, typename R>
struct substitute<O, S, R, 2>
{	typedef O type;
};

template<typename S, typename R>
struct substitute<S, S, R, 0>
{	typedef R type;
};
template<typename S, typename R>
struct substitute<S, S, R, 1>
{	typedef R type;
};
template<typename S, typename R>
struct substitute<S, S, R, 2>
{	typedef R type;
};


template<typename T0, typename T1, typename S, typename R>
struct substitute<addition<T0, T1>, S, R, 1>
{	typedef addition<
		typename substitute<T0, S, R, 0>::type, 
		typename substitute<T1, S, R, 0>::type
	> type;
};
template<typename T0, typename T1, typename S, typename R>
struct substitute<multiplication<T0, T1>, S, R, 1>
{	typedef multiplication<
		typename substitute<T0, S, R, 0>::type, 
		typename substitute<T1, S, R, 0>::type
	> type;
};
template<typename T0, typename T1, typename S, typename R>
struct substitute<divison<T0, T1>, S, R, 1>
{	typedef divison<
		typename substitute<T0, S, R, 0>::type, 
		typename substitute<T1, S, R, 0>::type
	> type;
};
template<typename T0, typename T1, typename S, typename R>
struct substitute<subtraction<T0, T1>, S, R, 0>
{	typedef subtraction<
		typename substitute<T0, S, R, 0>::type, 
		typename substitute<T1, S, R, 0>::type
	> type;
};
template<typename T0, typename S, typename R>
struct substitute<minus<T0>, S, R, 0>
{	typedef minus<
		typename substitute<T0, S, R, 0>::type
	> type;
};
template<typename T0, typename S, typename R>
struct substitute<T0, minus<S>, R, 2>
{	typedef typename substitute<T0, S, minus<R>, 0>::type type;
};
template<typename T0, typename T1, typename T2, typename T3>
struct substitute<T0, pow_<T1, T2>, T3, 2>
{	typedef typename substitute<T0, T1, pow_<T3, minus<T2> >, 0>::type type;
};
typedef multiplication<
	real_value<2, 0>::type,
	asin_<one>::type
>::type pi;

}
}
#endif //! compile_time_expression_h_included
